package cn.jx.cjm.security.support;

import cn.jx.cjm.common.base.BaseRequest;
import cn.jx.cjm.common.enums.BizExceptionEnum;
import cn.jx.cjm.common.enums.StatusEnum;
import cn.jx.cjm.common.exception.BizException;
import cn.jx.cjm.common.util.BeanUtils;
import cn.jx.cjm.security.common.config.UserTokenProperties;
import cn.jx.cjm.security.common.constant.SecuritySystemConstants;
import cn.jx.cjm.security.common.util.SecurityUtils;
import cn.jx.cjm.security.dto.request.SysUserRequest;
import cn.jx.cjm.security.dto.response.SysUserResponse;
import cn.jx.cjm.security.entity.SysUser;
import cn.jx.cjm.security.entity.SysUserDepartment;
import cn.jx.cjm.security.entity.SysUserRole;
import cn.jx.cjm.security.service.ISysUserDepartmentService;
import cn.jx.cjm.security.service.ISysUserRoleService;
import cn.jx.cjm.security.service.ISysUserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 管理员信息 业务处理层
 *
 * @author James Chen
 * @since 2019-12-16
 */

@Service
public class SysUserSupportService {

    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysUserRoleService sysUserRoleService;
    @Autowired
    private ISysUserDepartmentService sysUserDepartmentService;
    @Autowired
    private UserTokenProperties userTokenProperties;


    
    public IPage<SysUserResponse> list(BaseRequest<SysUser> request) {

        //查询数据
        QueryWrapper<SysUser> sysUserQueryWrapper = request.getQueryWrapper();
        sysUserQueryWrapper.ne("id", SecuritySystemConstants.SUPER_ADMIN_ID);
        IPage<SysUser> sysUserPage = sysUserService.page(request.getPage(),sysUserQueryWrapper);
        //定义返回结果
        IPage<SysUserResponse> result = new Page<>();
        result.setTotal(sysUserPage.getTotal());
        result.setCurrent(sysUserPage.getCurrent());
        result.setSize(sysUserPage.getSize());
        result.setPages(sysUserPage.getPages());
        //转类数据
        List<SysUserResponse> responseList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(sysUserPage.getRecords())) {
            Set<Integer> userIds = sysUserPage.getRecords().stream().map(SysUser::getId).collect(Collectors.toSet());
            //获取用户角色
            QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
            sysUserRoleQueryWrapper.in("sys_user_id", userIds);
            List<SysUserRole> sysUserRoleList = sysUserRoleService.list(sysUserRoleQueryWrapper);
            Map<Integer, List<SysUserRole>> userRolesMap = sysUserRoleList.stream().collect(Collectors.groupingBy(SysUserRole::getSysUserId));
            // 获取用户部门
            QueryWrapper<SysUserDepartment> sysUserDepartmentQueryWrapper = new QueryWrapper<>();
            sysUserDepartmentQueryWrapper.in("sys_user_id", userIds);
            List<SysUserDepartment> sysUserDepartmentList = sysUserDepartmentService.list(sysUserDepartmentQueryWrapper);
            Map<Integer, List<SysUserDepartment>> departmentMap = sysUserDepartmentList.stream().collect(Collectors.groupingBy(SysUserDepartment::getSysUserId));

            for (SysUser temp : sysUserPage.getRecords()) {
                SysUserResponse response = new SysUserResponse();
                BeanUtils.copyPropertiesIgnoreNull(temp, response);

                List<SysUserRole> sysUserRoleListTemp = userRolesMap.get(temp.getId());
                if (!CollectionUtils.isEmpty(sysUserRoleListTemp)) {
                    response.setSysRoleIds(sysUserRoleListTemp.stream().map(SysUserRole::getSysRoleId).collect(Collectors.toList()));
                }

                List<SysUserDepartment> sysUserDepartmentListTemp = departmentMap.get(temp.getId());
                if (!CollectionUtils.isEmpty(sysUserDepartmentListTemp)) {
                    response.setSysDepartmentIds(sysUserDepartmentListTemp.stream().map(SysUserDepartment::getSysDepartmentId).collect(Collectors.toList()));
                }

                responseList.add(response);
            }
        }
        result.setRecords(responseList);

        return result;
    }

    public List<SysUserResponse> options() {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "realName");
        queryWrapper.ne("id", SecuritySystemConstants.SUPER_ADMIN_ID);
        queryWrapper.eq("status", StatusEnum.NORMAL.getCode());
        List<SysUser> sysUserList = sysUserService.list(queryWrapper);
        if (CollectionUtils.isEmpty(sysUserList)) {
            return new ArrayList<>();
        } else {
            List<SysUserResponse> result = new ArrayList<>(sysUserList.size());
            for (SysUser sysUser : sysUserList) {
                SysUserResponse sysUserResponse = new SysUserResponse();
                BeanUtils.copyPropertiesIgnoreNull(sysUser, sysUserResponse);
                result.add(sysUserResponse);
            }
            return result;
        }
    }

    public SysUserResponse getOne(Integer id) {
        SysUserResponse result = new SysUserResponse();
        if (SecuritySystemConstants.SUPER_ADMIN_ID.equals(id)) {
            return result;
        }
        SysUser sysUser = sysUserService.getById(id);
        BeanUtils.copyPropertiesIgnoreNull(sysUser, result);
        return result;
    }

    @Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
    public void save(SysUserRequest request) {
        LocalDateTime nowTime = LocalDateTime.now();
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        SysUser sysUser = new SysUser();
        BeanUtils.copyPropertiesIgnoreNull(request, sysUser);
        sysUser.setCreateTime(nowTime);
        sysUser.setUpdateTime(nowTime);
        String password = sysUser.getPassword();
        if (StringUtils.isEmpty(password)) {
            //设置默认密码
            password = userTokenProperties.getDefaultPassword();
        }
        //加密明文密码
        sysUser.setPassword(bCryptPasswordEncoder.encode(password));
        sysUserService.save(sysUser);
        List<SysUserRole> sysUserRoleList = copySysUserRole(request.getSysRoleIds(), sysUser.getId(), nowTime);
        sysUserRoleService.saveBatch(sysUserRoleList);
        List<SysUserDepartment> sysUserDepartments = copySysUserDepartment(request.getSysDepartmentIds(), sysUser.getId(), nowTime);
        sysUserDepartmentService.saveBatch(sysUserDepartments);
    }

    @Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
    public void update(SysUserRequest request) {
        if (SecuritySystemConstants.SUPER_ADMIN_ID.equals(request.getId())) {
            return;
        }
        LocalDateTime nowTime = LocalDateTime.now();
        SysUser sysUser = new SysUser();
        BeanUtils.copyPropertiesIgnoreNull(request, sysUser);
        String password = sysUser.getPassword();
        if (SecuritySystemConstants.SUPER_ADMIN_ID.equals(SecurityUtils.getSessionUser().getId()) && !StringUtils.isEmpty(password)) {
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            sysUser.setPassword(bCryptPasswordEncoder.encode(password));
        } else {
            sysUser.setPassword(null);
        }
        sysUserService.updateById(sysUser);
        if (!CollectionUtils.isEmpty(request.getSysRoleIds())) {

            QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
            sysUserRoleQueryWrapper.eq("sys_user_id", sysUser.getId());
            sysUserRoleService.remove(sysUserRoleQueryWrapper);
            List<SysUserRole> sysUserRoleList = copySysUserRole(request.getSysRoleIds(), sysUser.getId(), nowTime);
            sysUserRoleService.saveBatch(sysUserRoleList);
        }
        if (!CollectionUtils.isEmpty(request.getSysDepartmentIds())) {
            QueryWrapper<SysUserDepartment> sysUserDepartmentQueryWrapper = new QueryWrapper<>();
            sysUserDepartmentQueryWrapper.eq("sys_user_id", sysUser.getId());
            sysUserDepartmentService.remove(sysUserDepartmentQueryWrapper);
            List<SysUserDepartment> sysUserDepartments = copySysUserDepartment(request.getSysDepartmentIds(), sysUser.getId(), nowTime);
            sysUserDepartmentService.saveBatch(sysUserDepartments);
        }

    }

    public void updateLastLoginTime(Integer id) {
        SysUser sysUser = new SysUser();
        sysUser.setId(id);
        sysUser.setLastLoginTime(LocalDateTime.now());
        sysUserService.updateById(sysUser);
    }

    /**
     * 重置密码
     *
     * @param id 管理员id
     */
    public String resetSysUserPassword(Integer id) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        SysUser sysUser = new SysUser();
        sysUser.setId(id);
        sysUser.setPassword(bCryptPasswordEncoder.encode(userTokenProperties.getDefaultPassword()));
        sysUserService.updateById(sysUser);
        return userTokenProperties.getDefaultPassword();
    }

    public void remove(Integer id) {
        sysUserService.removeById(id);
    }

    /**
     * 拷贝管理员权限
     *
     * @param roleIds   角色id
     * @param sysUserId 管理员id
     * @param nowTime   当前时间
     * @return .
     */
    private static List<SysUserRole> copySysUserRole(List<Integer> roleIds, Integer sysUserId, LocalDateTime nowTime) {
        List<SysUserRole> result = new ArrayList<>(roleIds.size());
        for (Integer roleId : roleIds) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setSysUserId(sysUserId);
            sysUserRole.setSysRoleId(roleId);
            sysUserRole.setCreateTime(nowTime);
            result.add(sysUserRole);
        }
        return result;
    }

    /**
     * 拷贝管理员部门
     * @param departmentIds
     * @param sysUserId
     * @param nowTime
     * @return
     */
    private static List<SysUserDepartment> copySysUserDepartment(List<Integer> departmentIds, Integer sysUserId, LocalDateTime nowTime) {
        List<SysUserDepartment> result = new ArrayList<>(departmentIds.size());
        for (Integer departmentId : departmentIds) {
            SysUserDepartment sysUserDepartment = new SysUserDepartment();
            sysUserDepartment.setSysUserId(sysUserId);
            sysUserDepartment.setSysDepartmentId(departmentId);
            sysUserDepartment.setCreateTime(nowTime);
            result.add(sysUserDepartment);
        }
        return result;


    }
}

